﻿using ET;
using FairyGUI;
using System;
using System.Collections.Generic;

namespace Core
{
    public abstract class FGUIWindow<T> : Window, IFGUIWindow where T : GComponent
    {
        private Func<string, Type> binderFunc;
        protected T m_root;

        public bool isVaild { get; private set; } = false;
        public bool IsDisposed { get; protected set; }

        public async ETTask LoadAsync(Func<string, Type> binderFunc, params object[] args)
        {
            this.binderFunc = binderFunc;
            Type type = typeof(T);

            // FairyGUI 数据绑定类型 UIObjectFactory.SetPackageItemExtension
            await Binder(binderFunc, type);

            // 创建UI界面
            var method = type.GetMethod("CreateInstance");
            m_root = method.Invoke(null, null) as T;
            if (m_root == null)
            {
                Log.Debug($"load {type} fail!");
                return;
            }
            contentPane = m_root;
            m_root.SetSize(GRoot.inst.width, GRoot.inst.height);
            m_root.AddRelation(GRoot.inst, RelationType.Size);
            OnEndLoad(args);
            isVaild = true;
            Log.Debug($"Load {type} succeed");
        }
        protected async ETTask<A> CreateWidget<A, K>(K root = default, params object[] args) where A : class, IFGUIWidget<K> where K :  GObject
        {
            Type type = typeof(K);
            if (root == null)
            {
                await Binder(binderFunc, typeof(K));
                var method = type.GetMethod("CreateInstance");
                root = method.Invoke(null, null) as K;
            }

            if (root == null)
            {
                Log.Error($"create widget {typeof(A)} fail!");
                return default;
            }

            var widget = Activator.CreateInstance(typeof(A)) as A;
            widget.Initialize(root, args);

            World.Main.EventSystem.RegisterSystem(widget);
            return widget;
        }


        protected virtual void OnEndLoad(params object[] args)
        {

        }

        private async ETTask Binder(Func<string, Type> binderFunc, Type type)
        {
            var field = type.GetField("PackageName");
            if (field == null)
            {
                Log.Error($"find {type} field packageName fail!");
                return;
            }

            var packageName = field.GetValue(null) as string;
            if (string.IsNullOrEmpty(packageName))
            {
                Log.Error($"get {type} field packageName value fail!");
                return;
            }
            var binderType = binderFunc(packageName);
            if (binderType == null)
            {
                Log.Error($"find {type} binder fail!");
                return;
            }

            var assetBundle = await World.GetComponent<ResourceComponent>().LoadAssetBundleAsync(packageName, true);
            //if (assetBundle == null)
            //    return;

            var binder = Activator.CreateInstance(binderType) as IBinder;
            binder?.BindAll();
        }

        public override void Dispose()
        {
            base.Dispose();
            binderFunc = null;
            m_root?.Dispose();
        }
    }
}